﻿using System;
using BizElements.Core;

namespace BizElements.BusinessLayer
{
    /// <summary>Dummy implementation of <see cref="IEntitySecurityProvider"/> interface for use in applications that don't require 
    /// entity security provider or use DBMS for which entity security provided database objecta are not developed, yet.
    /// Gives maximum privileges to users.</summary>
    /// <remarks>By default <see cref="SecurityUtil"/> and <see cref="SecurityProviderFactory"/> use <b>BizElements.BusinessLayer.EntitySecurityProvider</b>.
    /// This can be overrided in <b>appSettings</b> section of Web.config file. Example:
    /// <code>
    /// &lt;add key="BizElements.BusinessLayer.SecurityProviderFactory.DefaultProviderAssembly" value="BizElements.BusinessLayer"/&gt;
    /// &lt;add key="BizElements.BusinessLayer.SecurityProviderFactory.DefaultProviderClass" value="BizElements.BusinessLayer.NullEntitySecurityProvider"/&gt;
    /// </code>
    /// </remarks>
    public class NullEntitySecurityProvider : IEntitySecurityProvider
    {
        #region IEntitySecurityProvider.

        /// <summary>Returns <see cref="AccessFilterOptions.None"/>.</summary>
        public virtual AccessFilterOptions DefaultOptions
        {
            get { return AccessFilterOptions.None; }
        }

        /// <summary>Returns <b>true</b> if entity implement record ownership, i.e. if it has organization ID or owner ID or team ID or unit ID field.</summary>
        /// <param name="entity">Business object.</param>
        /// <returns><b>true</b> if entity has at least one ownership field defined in its descriptor; otherwise <b>false</b></returns>
        public bool ImplementsRecordOwnership(IBusinessObject entity)
        {
            var meta = entity.GetDescriptor();
            bool hasOwnerOrTeamOrUnitField = !string.IsNullOrEmpty(meta.Fields.OrganizationIdPropertyName) || !string.IsNullOrEmpty(meta.Fields.OwnerIdPropertyName) || !string.IsNullOrEmpty(meta.Fields.TeamIdPropertyName) || !string.IsNullOrEmpty(meta.Fields.UnitIdPropertyName);
            return hasOwnerOrTeamOrUnitField;
        }

        /// <summary>Does nothing.</summary>
        /// <param name="descriptor">Ignored.</param>
        /// <param name="user">Ignored.</param>
        /// <param name="query">Ignored.</param>
        /// <param name="accessMode">Ignored.</param>
        /// <param name="options">Ignored.</param>
        public virtual void ApplyAccessFilterToQuery(IBusinessObjectDescriptor descriptor, IActor user, SelectStatement query, AccessMode accessMode, AccessFilterOptions options)
        {
        }

        /// <summary>Does nothing.</summary>
        /// <param name="descriptor">Ignored.</param>
        /// <param name="user">Ignored.</param>
        /// <param name="engine">Ignored.</param>
        /// <param name="accessMode">Ignored.</param>
        /// <param name="options">Ignored.</param>
        public virtual void ApplyAccessFilterToSearchEngine(IBusinessObjectDescriptor descriptor, IActor user, SearchEngine engine, AccessMode accessMode, AccessFilterOptions options)
        {
        }

        /// <summary>Does nothing.</summary>
        /// <param name="descriptor">Ignored.</param>
        /// <param name="user">Ignored.</param>
        /// <param name="sourceTable">Ignored.</param>
        /// <param name="relations">Ignored.</param>
        /// <param name="where">Ignored.</param>
        /// <param name="accessMode">Ignored.</param>
        /// <param name="options">Ignored.</param>
        public virtual void ApplyAccessFilterToQuery(IBusinessObjectDescriptor descriptor, IActor user, IDbTable sourceTable, RelationBucket relations, SearchCondition where, AccessMode accessMode, AccessFilterOptions options)
        {
        }

        /// <summary>Returns <b>true</b>.</summary>
        /// <param name="user">Ignored.</param>
        /// <param name="entity">Ignored.</param>
        /// <returns><b>true</b></returns>
        public virtual bool CanReadEntity(IActor user, IBusinessObject entity)
        {
            return true;
        }

        /// <summary>Returns <b>true</b>.</summary>
        /// <param name="user">Ignored.</param>
        /// <param name="entity">Ignored.</param>
        /// <returns><b>true</b></returns>
        public virtual bool CanSaveEntity(IActor user, IBusinessObject entity)
        {
            return true;
        }

        /// <summary>Returns <b>true</b>.</summary>
        /// <param name="user">Ignored.</param>
        /// <param name="entity">Ignored.</param>
        /// <returns><b>true</b></returns>
        public virtual bool CanCreateEntity(IActor user, IBusinessObject entity)
        {
            return true;
        }

        /// <summary>Returns <b>true</b>.</summary>
        /// <param name="user">Ignored.</param>
        /// <param name="entity">Ignored.</param>
        /// <returns><b>true</b></returns>
        public virtual bool CanUpdateEntity(IActor user, IBusinessObject entity)
        {
            return true;
        }

        /// <summary>Returns <b>true</b>.</summary>
        /// <param name="user">Ignored.</param>
        /// <param name="entity">Ignored.</param>
        /// <returns><b>true</b></returns>
        public virtual bool CanDeleteEntity(IActor user, IBusinessObject entity)
        {
            return true;
        }

        /// <summary>Returns <b>true</b>.</summary>
        /// <param name="user">Ignored.</param>
        /// <param name="entity">Ignored.</param>
        /// <returns><b>true</b></returns>
        public virtual bool CanAssignEntity(IActor user, IBusinessObject entity)
        {
            return true;
        }

        /// <summary>Creates an instance of <see cref="Actor"/> class but doesn't fetch data from the data source.</summary>
        /// <param name="username">Username.</param>
        /// <returns>Instance of <see cref="Actor"/> class with the specified name.</returns>
        public virtual IActor FetchActorInfo(string username)
        {
            return new Actor(null, username);
        }

        #endregion
    }
}
